﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Data;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using Microsoft.Win32;
using NLog;
using SellAvi.Classes;
using SellAvi.Model;
using SellAvi.Properties;
using SellAvi.Services;
using SellAvi.Views;

namespace SellAvi.ViewModel
{
    public class MultipleProductsViewModel : ViewModelBase
    {

        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
        public RelayCommand DeleteSelectedProductsCommand { get; set; }
        public RelayCommand MarkProductsCommand { get; set; }
        public RelayCommand ExportToExcelCommand { get; set; }
        public RelayCommand ImportProductsCommand { get; set; }
        public RelayCommand AddNewProductCommand { get; set; }
        public RelayCommand<AvitoProduct> EditProductCommand { get; set; }
        public RelayCommand<AvitoProduct> BrowseProductCommand { get; set; }
        public RelayCommand<string> FilterProductsCommand { get; set; }
        public RelayCommand<IList> ProductsSelectionChangedCommand { get; set; }

        private IList SelectedAvitoProducts { get; set; }
        private IDataAccessService ServiceProxy { get; set; }
        public ICollectionView AvitoProducts { get; set; }
        private AvitoUser _currentAvitoUser;


        public MultipleProductsViewModel(IDataAccessService servPxy)
        {
            //Источник данных БД
            ServiceProxy = servPxy;

            //Список товаров
            AvitoProducts = CollectionViewSource.GetDefaultView(ServiceProxy.GetProducts());
            SelectedAvitoProducts = new List<AvitoProduct>();

            //Получение информации об авторизированном пользователе
            Messenger.Default.Register<AvitoUser>(this, (au) =>
            {
                //Установка фильтра списка товаров
                _currentAvitoUser = au;
                AvitoProducts.Filter = new Predicate<object>(ApplyUserFilter);
                RaisePropertyChanged("AvitoProducts");
            });


            //Создание директории для спарсеных изображений
            Directory.CreateDirectory("images");

            //Команды для работы с окном "Список товаров"
            DeleteSelectedProductsCommand = new RelayCommand(DeleteSelectedProducts);
            MarkProductsCommand = new RelayCommand(CreatePublicationTask);
            ExportToExcelCommand = new RelayCommand(ExportToExcel);
            ImportProductsCommand = new RelayCommand(OpenProductImport);
            AddNewProductCommand = new RelayCommand(EditSelectedProduct);
            EditProductCommand = new RelayCommand<AvitoProduct>(NavigateToDetails);
            BrowseProductCommand = new RelayCommand<AvitoProduct>(BrowsePruduct);
            FilterProductsCommand = new RelayCommand<string>(ApplyFilter);
            ProductsSelectionChangedCommand = new RelayCommand<IList>(ProductsSelectionChanged);


        }

        private void EditSelectedProduct()
        {
            if (SelectedAvitoProducts.Count == 1)
            {
                NavigateToDetails((AvitoProduct)SelectedAvitoProducts[0]);
            }
            else
            {
                NavigateToDetails((AvitoProduct)AvitoProducts.CurrentItem);
            }


        }

        private void ProductsSelectionChanged(IList checkedElements)
        {
            SelectedAvitoProducts.Clear();
            if (checkedElements != null)
            {
                foreach (var element in checkedElements)
                {

                    SelectedAvitoProducts.Add(element as AvitoProduct);
                }
            }
        }

        private void DeleteSelectedProducts()
        {
            var result =
                MessageBox.Show(
                    String.Format("Вы действительно хотите удалить ({0}) товаров?", SelectedAvitoProducts.Count),
                    "Удаление товаров",
                    MessageBoxButton.YesNo, MessageBoxImage.Question);
            if (result == MessageBoxResult.Yes)
            {

                foreach (var item in SelectedAvitoProducts)
                {
                    ServiceProxy.DeleteProduct(item as AvitoProduct);
                }
                AvitoProducts.Refresh();
                SelectedAvitoProducts.Clear();
                RaisePropertyChanged("AvitoProducts");
            }

        }

        private void OpenProductImport()
        {
            new WindowProductImport().Show();
        }

        private void ExportToExcel()
        {
            if (SelectedAvitoProducts == null || SelectedAvitoProducts.Count == 0)
            {
                MessageBox.Show("Не выбраны товары для экспорта", "Мастер экспорта", MessageBoxButton.OK,
                    MessageBoxImage.Exclamation);
                return;

            }
            SaveFileDialog saveFileDialog1 = new SaveFileDialog
            {
                Filter = "CSV File|*.csv",
                Title = "Сохранение списка товаров"
            };
            saveFileDialog1.ShowDialog();

            if (saveFileDialog1.FileName != "")
            {
                try
                {
                    string csv = String.Empty;

                    //Получаем все доступные для экспорта свойства модели "товара" и совершаем экспорт
                    IEnumerable<PropertyInfo> props =
                        SelectedAvitoProducts[0].GetType()
                            .GetProperties()
                            .Where(m => m.GetCustomAttributes(typeof(ExportAllowedAttribute), true).Length > 0);

                    csv += String.Join(";", props.Select(prop => prop.Name)) + "\r\n";

                    foreach (var item in SelectedAvitoProducts)
                    {
                        var productFields = props.Select(pr => pr.GetValue(item)).Cast<string>().ToList();
                        //var productFields = props.Select(pr => (string)pr.GetValue(item) ?? "").ToList();
                        csv += String.Join(";", productFields.Select(f => "\"" + (f != null ? f.Replace("\"", "\"\"") : String.Empty) + "\"")) + "\r\n";
                    }

                    //Открытие файла и запись выбранных пользователем товаров
                    using (FileStream fs = (FileStream)saveFileDialog1.OpenFile())
                    {
                        fs.Write(Encoding.GetEncoding(1251).GetBytes(csv.ToString()), 0, Encoding.GetEncoding(1251).GetByteCount(csv.ToString()));

                    }

                    Process.Start(saveFileDialog1.FileName);

                }
                catch (Exception ex)
                {
                    Logger.Error(ex, "Произошла ошибка при экспорте товаров!");
                }
            }
        }



        private void CreatePublicationTask()
        {
            var taskList = new List<AvitoTask>();
            foreach (var selectedAvitoProduct in SelectedAvitoProducts)
            {
                taskList.Add(new TaskProductUploader((AvitoProduct)selectedAvitoProduct){TaskDelay = Settings.Default.PublicationTimeOut});
            }
            Messenger.Default.Send<List<AvitoTask>>(taskList);
        }

        private void NavigateToDetails(AvitoProduct ap)
        {
            if (ap != null)
            {
                new WindowAddProduct().Show();
                Messenger.Default.Send<AvitoProduct>(ap);
            }
        }

        private void BrowsePruduct(AvitoProduct ap)
        {
            if (ap != null && ap.PostedOnUrl != null)
            {
                IEHelpers.OpenWebBrowser(ap.PostedOnUrl);
            }
        }

        private bool ApplyUserFilter(object avitoProduct)
        {
            var ap = avitoProduct as AvitoProduct;
            return ap != null && ap.AvitoUser == _currentAvitoUser;
        }

        private bool ApplyPublishedFilter(object avitoProduct)
        {
            var ap = avitoProduct as AvitoProduct;
            return ap != null && ap.PostedOnUrl != null;
        }

        private void ApplyFilter(string filterName)
        {
            var currentFilter = (AvitoProducts.Filter != null) ? AvitoProducts.Filter.Method.Name : null;
            if (filterName == "ApplyUserFilter")
            {
                AvitoProducts.Filter = new Predicate<object>(ApplyUserFilter);
            }
            if (filterName == "ApplyPublishedFilter")
            {
                AvitoProducts.Filter = new Predicate<object>(ApplyPublishedFilter);
            }
            if (filterName == currentFilter)
            {
                AvitoProducts.Filter = null;
            }
            AvitoProducts.Refresh();
        }





    }
}
